﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Communication
{
    /// <summary>
    /// 自定义依赖注入容器
    /// </summary>
    public class DependencyContainer
    {
        // 存储注册的服务：key=接口类型，value=实现类型
        public readonly Dictionary<Type, Type> _serviceMap = new Dictionary<Type, Type>();

        // 存储具体类型→实例的映射（用于窗体等具体类）
        public readonly Dictionary<Type, object> _instanceMap = new Dictionary<Type, object>();

        // 注册具体类型（如 WinForm 窗体）
        public void RegisterType<TConcrete>() where TConcrete : class
        {
            _serviceMap[typeof(TConcrete)] = typeof(TConcrete); // 将具体类型映射到自身
        }

        // 注册具体类型并指定实例（单例场景）
        public void RegisterInstance<T>(T instance) where T : class
        {
            _instanceMap[typeof(T)] = instance;
        }        

        // 实例创建
        private object CreateInstance(Type implType)
        {
            var constructor = implType.GetConstructors().OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
            if (constructor == null)
            {
                return Activator.CreateInstance(implType);
            }
            var parameters = constructor.GetParameters()
                .Select(param => Resolve(param.ParameterType))
                .ToArray();
            return Activator.CreateInstance(implType, parameters);
        }

        public void RegisterAssemblies(string[] assemblyNames)
        {
            foreach (var assemblyName in assemblyNames)
            {
                RegisterAssembly(assemblyName);
            }
        }


        /// <summary>
        /// 扫描程序集并自动注册服务（接口 -> 实现类）
        /// </summary>
        /// <param name="assemblyName">程序集名称（如 "AppService"）</param>
        public void RegisterAssembly(string assemblyName)
        {
            try
            {
                // 加载程序集
                Assembly assembly = Assembly.Load(assemblyName);
                if (assembly == null)
                {
                    Console.WriteLine($"警告：未找到程序集 {assemblyName}，跳过扫描");
                    return;
                }

                // 扫描程序集中所有非抽象类（排除接口和抽象类）
                var implementationTypes = assembly.GetTypes()
                    .Where(t => !t.IsAbstract && !t.IsInterface && t.IsClass);

                foreach (var implType in implementationTypes)
                {
                    // 获取类实现的所有接口（排除系统接口，如 IDisposable）
                    var interfaces = implType.GetInterfaces()
                        .Where(i => i.Assembly != typeof(object).Assembly); // 过滤系统程序集中的接口

                    foreach (var @interface in interfaces)
                    {
                        // 注册：接口→实现类（若已有注册则跳过，避免重复）
                        if (!_serviceMap.ContainsKey(@interface))
                        {
                            _serviceMap.Add(@interface, implType);
                            Console.WriteLine($"已注册服务：{@interface.Name} → {implType.Name}（来自程序集：{assemblyName}）");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"扫描程序集 {assemblyName} 失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 解析服务（递归创建对象并注入依赖）
        /// </summary>
        /// <typeparam name="T">接口类型</typeparam>
        /// <returns>接口对应的实现类实例</returns>
        public T Resolve<T>()
        {
            return (T)Resolve(typeof(T));
        }

        // 优先检查具体类型注册或实例映射
        private object Resolve(Type type)
        {
            object instance;
            // 先检查是否有直接注册的实例（如单例）
            if (_instanceMap.TryGetValue(type, out instance))
            {
                return instance;
            }

            // 检查是否有具体类型注册（如窗体类）
            if (_serviceMap.TryGetValue(type, out Type implType) && implType == type)
            {
                // 直接创建具体类型实例（递归解析构造函数依赖）
                return CreateInstance(implType);
            }

            // 原有逻辑：解析接口→实现类
            if (_serviceMap.TryGetValue(type, out implType))
            {
                return CreateInstance(implType);
            }
            return instance;
            //throw new KeyNotFoundException($"未找到类型 {type.Name} 的注册信息");
        }

    }

}
